#include "rpc/client_processor.h"
#include "rpc/connection.h"
#include "include/rpc_helper.h"
#include "rpc/poller.h"
#include "rpc/buffer.h"
#include "rpc/rpc_util.h"
#include "rpc/protocol.h"

namespace urpc {

void ClientProcessor::SetConnection(Connection* conn) {
  {
    ScopedMutex m(&conn_mutex_);
    conn_.reset(conn);
  }

  ScopedMutex l(&req_mutex_);
  for (std::map<uint32, RpcRequestInfo*>::iterator it = req_map_.begin();
      it != req_map_.end(); ++it) {
    RpcRequestInfo* info = it->second;
    if (!SendRequest(info)) {
      return;
    }
  }
}

void ClientProcessor::HandleRead(Connection* conn, Buffer* buf) {
  CHECK(buf->ReadableSize() > HEADER_LENGTH);
  RpcHeader* bhs = (RpcHeader*) buf->Read(HEADER_LENGTH);

  RpcRequestInfo* info = NULL;
  {
    ScopedMutex l(&req_mutex_);
    std::map<uint32, RpcRequestInfo*>::iterator it = req_map_.find(bhs->id);
    CHECK(it != req_map_.end());
    RpcRequestInfo* info = it->second;
    req_map_.erase(it);
  }

  AutoRunner r(info->done);
}

bool ClientProcessor::SendRequest(RpcRequestInfo* info) {
  ScopedMutex l(&conn_mutex_);
  if (conn_.get() == NULL) {
    return false;
  }

  protocol_->HandleWrite(conn_.get(), info->rpc_id, info->func_id,
                         info->response);
  return true;
}

void ClientProcessor::CallMethod(RpcRequestInfo* info) {
  ScopedMutex l(&req_mutex_);
  req_map_.insert(std::make_pair(info->rpc_id, info));

  SendRequest(info);
}
}
